﻿using JewererBasic.Classes;
using JewererBasic.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using System.Web;

namespace JewererBasic.BO
{
    public class ComponentBO
    {
        /*Sang add for AdditionComponentController*/
        public static bool AddComplexComponent(COMPONENT component)
        {
            MSQDBEntities db = new MSQDBEntities();
            var query = db.COMPONENTs.Find(component.Id);
            if (query == null)
            {
                for (int i = 0; i < component.COMPONENT_MOLECULE.Count; i++)
                {
                    COMPONENT_MOLECULE molecule = component.COMPONENT_MOLECULE.ElementAt(i);
                    molecule.MainComponentId = component.Id;
                    db.COMPONENT_MOLECULE.Add(molecule);
                }
                component.COMPONENT_MOLECULE = null;
                db.COMPONENTs.Add(component);
                db.SaveChanges();
                return true;
            }
            return false;
        }
        public static string CheckComponentId(List<string> ids)
        {
            string result = "";
            MSQDBEntities db = new MSQDBEntities();
            foreach (var item in ids)
            {
                COMPONENT com = db.COMPONENTs.Find(item);
                if (com == null)
                {
                    result += "Can't find Component has id: " + item + "\r\n";
                }
            }
            return result;
        }

        /*End*/
        public static bool Add(COMPONENT component)
        {
            MSQDBEntities db = new MSQDBEntities();
            var query = from d in db.COMPONENTs
                        where d.Id.Equals(component.Id)
                        select d;
            if (query.Count() > 0)
                return false;
            component.DayCreate = DateTime.Now.Date;
            component.IdCreater = CurrentUser.UserID;
            if (component.Weight.HasValue)
            {
                component.Weight = Math.Round(component.Weight.Value, 3);
            }
            else
            {
                component.Weight = 0;
            }
            component.Dust = 0;
            db.COMPONENTs.Add(component);
            try
            {
                db.SaveChanges();
            }
            catch (Exception ex)
            {
                // validation error
                return false;
            }
            return true;
        }

        public static bool Delete(string id)
        {
            MSQDBEntities db = new MSQDBEntities();
            var query = db.COMPONENTs.Find(id);
            if (query != null)
            {
                try
                {
                    db.COMPONENTs.Remove(query);
                    db.SaveChanges();
                }
                catch (Exception ex)
                {
                    db.SaveChanges();
                    return true;
                }
            }
            return true;
        }

        public static bool Update(COMPONENT component)
        {
            MSQDBEntities db = new MSQDBEntities();
            var query = db.COMPONENTs.Find(component.Id);
            if (query != null)
            {
                query.Name = component.Name;
                query.IdCreater = CurrentUser.UserID;
                query.Decription = component.Decription;
                query.DayCreate = DateTime.Now.Date;
                query.IdUnit = component.IdUnit;
                query.IdType = component.IdType;
                try
                {
                    db.SaveChanges();
                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
            return false;
        }

        public static List<COMPONENT> Search(string id, string name)
        {
            MSQDBEntities db = new MSQDBEntities();
            var query = (from d in db.COMPONENTs
                         where d.Id.Contains(id) && d.Name.Contains(name)
                         select d).ToList();
            return query;
        }

        public static List<COMPONENT> Components()
        {
            MSQDBEntities db = new MSQDBEntities();
            return db.COMPONENTs.ToList();
        }

        public static bool Import(COMPONENT_IMPORT componentImport, List<COMPONENT_IMPORTDETAIL> details)
        {
            using (MSQDBEntities db = new MSQDBEntities())
            {
                // use transaction to prevent error on data.
                using (var scope = new TransactionScope())
                {
                    try
                    {
                        // add COMPONENT_import
                        componentImport.IdCreater = CurrentUser.UserID;
                        componentImport.DayMake = DateTime.Now.Date.Date;
                        db.COMPONENT_IMPORT.Add(componentImport);
                        db.SaveChanges();

                        // add COMPONENT_import_detail
                        for (int i = 0; i < details.Count; i++)
                        {
                            details[i].IdImport = componentImport.IdImport;
                            details[i].Weight = Math.Round(details[i].Weight, 3);
                            db.COMPONENT_IMPORTDETAIL.Add(details[i]);
                        }
                        db.SaveChanges();

                        // add weight component
                        for (int i = 0; i < details.Count; i++)
                        {
                            var query = db.COMPONENTs.Find(details[i].IdComponent);
                            if (query == null)
                                return false;
                            query.Weight += details[i].Weight;
                            if (query.Weight.HasValue)
                            {
                                query.Weight = Math.Round(query.Weight.Value, 3);
                            }
                        }
                        db.SaveChanges();
                        scope.Complete();
                    }
                    catch (Exception e)
                    {
                        return false;
                    }
                }
                return true;
            }
        }

        /// <summary>
        /// When creating bag, create BAG_component. 
        /// This function edits BAG_component by adding numb and weight
        /// </summary>
        /// <param name="idBag"></param>
        /// <param name="bagcomponents"></param>
        /// <returns></returns>
        public static bool ExportToBag(string idBag, int receiver, COMPONENT_EXPORTBAG COMPONENT_exportBag, List<BAG_COMPONENT> bagcomponents, List<ServiceComponent> listReasons)
        {
            for (int i = 0; i < bagcomponents.Count; i++)
            {
                bagcomponents[i].IdBag = idBag;
            }

            using (MSQDBEntities db = new MSQDBEntities())
            {
                using (var scope = new TransactionScope())
                {
                    try
                    {
                        // CREATE component EXPORT
                        // create COMPONENT_exportbag and save to db
                        COMPONENT_exportBag.IdBag = idBag;
                        COMPONENT_exportBag.IdCreater = CurrentUser.UserID;
                        COMPONENT_exportBag.DayMake = DateTime.Now.Date;
                        COMPONENT_exportBag.IdReceiver = receiver;
                        db.COMPONENT_EXPORTBAG.Add(COMPONENT_exportBag);
                        db.SaveChanges();
                        // create component export bag detail and save to db
                        for (int i = 0; i < bagcomponents.Count; i++)
                        {
                            COMPONENT_EXPORTBAGDETAIL sebd = new COMPONENT_EXPORTBAGDETAIL();
                            sebd.IdExport = COMPONENT_exportBag.IdExport;
                            sebd.IdComponent = bagcomponents[i].IdComponent;
                            sebd.Weight = Math.Round(bagcomponents[i].Weight, 3);
                            sebd.Reason = listReasons[i].Reason;
                            db.COMPONENT_EXPORTBAGDETAIL.Add(sebd);
                        }
                        db.SaveChanges();

                        // ADD NUMB AND WEIGHT IN BAG component
                        for (int i = 0; i < bagcomponents.Count; i++)
                        {
                            var query = db.BAG_COMPONENT.Find(idBag, bagcomponents[i].IdComponent);
                            if (query == null)
                                throw new Exception("Can't find BAG_component, maybe you've not creating BAG_component properly when creating bag!");
                            query.Weight += bagcomponents[i].Weight;
                            query.Weight = Math.Round(query.Weight, 3);
                            query.Dust += bagcomponents[i].Dust;
                            query.Dust = Math.Round(query.Dust, 3);
                        }
                        db.SaveChanges();

                        // subtract in component
                        // add weight to bag
                        for (int i = 0; i < bagcomponents.Count; i++)
                        {
                            var query = db.COMPONENTs.Find(bagcomponents[i].IdComponent);
                            if (query != null)
                            {                                
                                query.Weight -= bagcomponents[i].Weight;
                                query.Weight = Math.Round(query.Weight.Value, 3);
                                query.Dust -= bagcomponents[i].Dust;
                                query.Dust = Math.Round(query.Dust.Value, 3);

                                // add weight to bag
                                BAG b = db.BAGs.Find(bagcomponents[i].IdBag);
                                b.Current_Weight = Math.Round(b.Current_Weight + bagcomponents[i].Weight, 3);
                            }
                        }
                        db.SaveChanges();
                        scope.Complete();
                    }
                    catch (Exception e)
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        public static bool ExportToStaff(int idStaff, COMPONENT_EXPORTSTAFF se, List<COMPONENT_EXPORTSTAFFDETAIL> details)
        {
            using (MSQDBEntities db = new MSQDBEntities())
            {
                using (var scope = new TransactionScope())
                {
                    try
                    {
                        // create component exportstaff
                        se.DayMake = DateTime.Now.Date;
                        se.IdCreater = CurrentUser.UserID;
                        se.IdStaff = idStaff;
                        db.COMPONENT_EXPORTSTAFF.Add(se);
                        db.SaveChanges();
                        for (int i = 0; i < details.Count; i++)
                        {
                            details[i].IdExport = se.IdExport;
                            details[i].Weight = Math.Round(details[i].Weight, 3);
                            details[i].Dust = Math.Round(details[i].Dust, 3);
                            db.COMPONENT_EXPORTSTAFFDETAIL.Add(details[i]);
                        }
                        db.SaveChanges();

                        // subtractcomponent
                        for (int i = 0; i < details.Count; i++)
                        {
                            var query = db.COMPONENTs.Find(details[i].IdComponent);
                            if (query != null)
                            {
                                query.Weight -= details[i].Weight;
                                query.Weight = Math.Round(query.Weight.Value, 3);
                                query.Dust -= details[i].Dust;
                                query.Dust = Math.Round(query.Dust.Value, 3);
                            }
                        }
                        db.SaveChanges();
                        scope.Complete();
                    }
                    catch (Exception ex)
                    {
                        return false;
                    }
                }
                return true;
            }
        }

        public static List<BAG_COMPONENT> Bagcomponents(string idBag)
        {
            MSQDBEntities db = new MSQDBEntities();
            var query = from d in db.BAG_COMPONENT
                        where d.IdBag.Equals(idBag)
                        select d;
            return query.ToList();
        }

        public static void Something()
        {

            using (MSQDBEntities ctx = new MSQDBEntities())
            {
                using (var scope = new TransactionScope())
                {

                    scope.Complete();
                }
            }
        }

        public static List<HistoryComponent> History(string idComponent, DateTime? dateFrom, DateTime? dateTo, bool isImport, bool isExportBag, bool isExportStaff)
        {
            List<HistoryComponent> result = new List<HistoryComponent>();
            MSQDBEntities db = new MSQDBEntities();

            // get import history
            if (isImport == true)
            {
                var queryImport = from d in db.COMPONENT_IMPORT
                                  select d;

                if (dateFrom.HasValue)
                {
                    queryImport = queryImport.Where(d => d.DayMake >= dateFrom.Value);
                }
                if (dateTo.HasValue)
                {
                    queryImport = queryImport.Where(d => d.DayMake <= dateTo.Value);
                }

                var imports = queryImport.ToList();
                if (imports.Count > 0)
                {
                    foreach (var item in imports)
                    {
                        foreach (var Component in item.COMPONENT_IMPORTDETAIL)
                        {
                            if (String.IsNullOrEmpty(idComponent) == true || Component.IdComponent.Equals(idComponent))
                            {
                                result.Add(new HistoryComponent(item, Component));
                            }
                        }
                    }
                }
            }

            // get exportbag history
            if (isExportBag == true)
            {
                var queryExportBag = from d in db.COMPONENT_EXPORTBAG
                                     select d;

                if (dateFrom.HasValue)
                {
                    queryExportBag = queryExportBag.Where(d => d.DayMake >= dateFrom.Value);
                }
                if (dateTo.HasValue)
                {
                    queryExportBag = queryExportBag.Where(d => d.DayMake <= dateTo.Value);
                }

                var exportBags = queryExportBag.ToList();
                if (exportBags.Count > 0)
                {
                    foreach (var item in exportBags)
                    {
                        foreach (var bag in item.COMPONENT_EXPORTBAGDETAIL)
                        {
                            if (String.IsNullOrEmpty(idComponent) == true || bag.IdComponent.Equals(idComponent))
                                result.Add(new HistoryComponent(item, bag));
                        }
                    }
                }
            }

            // get exportstaff history
            if (isExportStaff == true)
            {
                var queryExportStaff = from d in db.COMPONENT_EXPORTSTAFF
                                       select d;

                if (dateFrom.HasValue)
                {
                    queryExportStaff = queryExportStaff.Where(d => d.DayMake >= dateFrom.Value);
                }
                if (dateTo.HasValue)
                {
                    queryExportStaff = queryExportStaff.Where(d => d.DayMake <= dateTo.Value);
                }

                var exportStaffs = queryExportStaff.ToList();
                if (exportStaffs.Count > 0)
                {
                    foreach (var item in exportStaffs)
                    {
                        foreach (var staff in item.COMPONENT_EXPORTSTAFFDETAIL)
                        {
                            if (String.IsNullOrEmpty(idComponent) == true || staff.IdComponent.Equals(idComponent))
                                result.Add(new HistoryComponent(item, staff));
                        }
                    }
                }
            }
            return result;
        }
    }
}